package net.aiion.weave;

import net.aiion.weave.asm.AnnotationVisitor;
import net.aiion.weave.asm.ClassWriter;
import net.aiion.weave.asm.Label;
import net.aiion.weave.asm.MethodVisitor;
import net.aiion.weave.asm.Opcodes;
import net.aiion.weave.asm.Type;

public class ReceivingClassDump implements Opcodes
{
    public static byte[] dump() throws Exception {
        ClassWriter cw = new ClassWriter(0);
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "org/weaveframework/conversions/impl/ReceivingClass", null,
            "java/lang/Object", new String[] {
                "org/weaveframework/messaging/spi/Receiver"
            });

        cw.visitSource("ReceivingClass.java", null);

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(8, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(9, l1);
            mv.visitInsn(RETURN);
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitLocalVariable("this", "Lorg/weaveframework/conversions/impl/ReceivingClass;", null, l0, l2, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "receiveMessage", "(Lorg/weaveframework/messaging/spi/ReceiverContext;)V",
                null, null);
            mv.visitCode();

            Label l1 = new Label();
            mv.visitLdcInsn("no-return-type");
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getQueueName",
                "()Ljava/lang/String;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
            mv.visitJumpInsn(IFEQ, l1);
            mv.visitLdcInsn(Type.getType("Lorg/weaveframework/conversions/impl/Message1;"));
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getMessage",
                "()Ljava/lang/Object;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "isAssignableFrom", "(Ljava/lang/Class;)Z");
            mv.visitJumpInsn(IFEQ, l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getMessage",
                "()Ljava/lang/Object;");
            mv.visitTypeInsn(CHECKCAST, "org/weaveframework/conversions/impl/Message1");
            mv.visitMethodInsn(INVOKEVIRTUAL, "org/weaveframework/conversions/impl/ReceivingClass", "receiveMessage1",
                "(Lorg/weaveframework/conversions/impl/Message1;)V");
            mv.visitLabel(l1);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

            Label l4 = new Label();
            mv.visitLdcInsn("with-return-type");
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getQueueName",
                "()Ljava/lang/String;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
            mv.visitJumpInsn(IFEQ, l4);
            mv.visitLdcInsn(Type.getType("Lorg/weaveframework/conversions/impl/Message2;"));
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getMessage",
                "()Ljava/lang/Object;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "isAssignableFrom", "(Ljava/lang/Class;)Z");
            mv.visitJumpInsn(IFEQ, l4);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getMessage",
                "()Ljava/lang/Object;");
            mv.visitTypeInsn(CHECKCAST, "org/weaveframework/conversions/impl/Message2");
            mv.visitMethodInsn(INVOKEVIRTUAL, "org/weaveframework/conversions/impl/ReceivingClass", "receiveMessage2",
                "(Lorg/weaveframework/conversions/impl/Message2;)Lorg/weaveframework/conversions/impl/Result;");
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "setResult",
                "(Ljava/lang/Object;)V");
            mv.visitLabel(l4);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

            Label l7 = new Label();
            mv.visitLdcInsn("with-context");
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/messaging/spi/ReceiverContext", "getQueueName",
                "()Ljava/lang/String;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
            mv.visitJumpInsn(IFEQ, l7);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, "org/weaveframework/conversions/impl/ReceivingClass", "receiveMessage3",
                "(Lorg/weaveframework/messaging/spi/ReceiverContext;)V");
            mv.visitLabel(l7);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitInsn(RETURN);
            mv.visitMaxs(3, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "receiveMessage1", "(Lorg/weaveframework/conversions/impl/Message1;)V",
                null, null);
            {
                av0 = mv.visitAnnotation("Lorg/weaveframework/messaging/Receives;", true);
                av0.visit("value", "no-return-type");
                av0.visitEnd();
            }
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(32, l0);
            mv.visitInsn(RETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lorg/weaveframework/conversions/impl/ReceivingClass;", null, l0, l1, 0);
            mv.visitLocalVariable("aMessage", "Lorg/weaveframework/conversions/impl/Message1;", null, l0, l1, 1);
            mv.visitMaxs(0, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "receiveMessage2",
                "(Lorg/weaveframework/conversions/impl/Message2;)Lorg/weaveframework/conversions/impl/Result;", null,
                null);
            {
                av0 = mv.visitAnnotation("Lorg/weaveframework/messaging/Receives;", true);
                av0.visit("value", "with-return-type");
                av0.visitEnd();
            }
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(36, l0);
            mv.visitTypeInsn(NEW, "org/weaveframework/conversions/impl/Result");
            mv.visitInsn(DUP);
            mv.visitMethodInsn(INVOKESPECIAL, "org/weaveframework/conversions/impl/Result", "<init>", "()V");
            mv.visitInsn(ARETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lorg/weaveframework/conversions/impl/ReceivingClass;", null, l0, l1, 0);
            mv.visitLocalVariable("aMessage", "Lorg/weaveframework/conversions/impl/Message2;", null, l0, l1, 1);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "receiveMessage3", "(Lorg/weaveframework/messaging/spi/ReceiverContext;)V",
                null, null);
            {
                av0 = mv.visitAnnotation("Lorg/weaveframework/messaging/Receives;", true);
                av0.visit("value", "with-context");
                av0.visitEnd();
            }
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(41, l0);
            mv.visitInsn(RETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lorg/weaveframework/conversions/impl/ReceivingClass;", null, l0, l1, 0);
            mv.visitLocalVariable("aReceiverContext", "Lorg/weaveframework/messaging/spi/ReceiverContext;", null, l0,
                l1, 1);
            mv.visitMaxs(0, 2);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }
}
